package client_gui_chat;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTextArea;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;

import streaming.Call;
import utils.ImageCreator;
import client.ClientApplication;
import client.ClientBindObject;
import client_gui.AvatarDialog;


/**
 * @author UrosKrkic & Radivoje Popovic
 */
public class StreamingPanel extends JPanel {
	
	public static final int NO_ANSWER	= 0;
	public static final int YES_ANSWER	= 1;
	
	
	private JPanel peerVideo;
	private JPanel userVideo;
	private JSlider peerVolume;
	private JSlider userVolume;
	private JCheckBox peerMute;
	private JCheckBox userMute;
	private JSeparator separator1;
	private JProgressBar userCalling;
	private JProgressBar peerCalling;
	private JButton userAvatar;
	private JButton peerAvatar;
	private JButton yesButton;
	private JButton noButton;
	private JButton audioButton;
	private JButton videoButton;
	private JButton stopCallButton;
	private JCheckBox monitor;
	private JTextArea callingMessage;
	
	private ChatDialog owner;
	
	private JLabel noVideoPicture;
	private JLabel noMonitorPicture;
	
	
	public StreamingPanel(ChatDialog owner) {
		this.owner = owner;
		initComponents();
	}

	private CardLayout peerVideoCardLayout;
	private CardLayout userVideoCardLayout;
	
	private JPanel getPeerVideoPanel() {
		if (peerVideo == null) {
			peerVideo = new JPanel();
			peerVideo.setLayout(peerVideoCardLayout);
			peerVideo.setBorder(LineBorder.createBlackLineBorder());
			peerVideo.setBounds(10, 10, 176, 144);
			
			// ovako ne moze - dokumentacija laze
//			peerVideoCardLayout.addLayoutComponent(getNoVideoPanel(), "c1");
//			peerVideoCardLayout.addLayoutComponent(getCallAcceptPanel(), "c2");
//			peerVideoCardLayout.addLayoutComponent(getVideoPanel(), "c3");
			
			peerVideo.add(getPeerNoVideo(), "c1");
			peerVideo.add(getPeerCallAccept(), "c2");
			peerVideo.add(getPeerVideo(), "c3");
			
			peerVideoCardLayout.show(peerVideo, "c1");
		}
		return peerVideo;
	}
	
	
	private JPanel getUserVideoPanel() {
		if (userVideo == null) {
			userVideo = new JPanel();
			userVideo.setLayout(userVideoCardLayout);
			userVideo.setBorder(LineBorder.createBlackLineBorder());
			userVideo.setBounds(10, 180, 128, 96);
			
			userVideo.add(getUserNoVideo(), "c1");
			userVideo.add(getUserVideo(), "c2");
			
			userVideoCardLayout.show(userVideo, "c1");
		}
		return userVideo;
	}
	
	
	public JSlider getPeerVolumeSlider() {
		if (peerVolume == null) {
			peerVolume = new JSlider();
			peerVolume.setOrientation(SwingConstants.VERTICAL);
			peerVolume.setBounds(200, 60, peerVolume.getPreferredSize().width, 50);
		}
		return peerVolume;
	}
	
	
	private JSlider getUserVolumeSlider() {
		if (userVolume == null) {
			userVolume = new JSlider();
			userVolume.setOrientation(SwingConstants.VERTICAL);
			userVolume.setBounds(150, 175, userVolume.getPreferredSize().width, 50);
		}
		return userVolume;
	}
	
	
	public JCheckBox getPeerMute() {
		if (peerMute == null) {
			peerMute = new JCheckBox();
			peerMute.setText("Mute");
			peerMute.setBounds(new Rectangle(new Point(200, 110), peerMute.getPreferredSize()));
		}
		return peerMute;
	}
	
	
	private JCheckBox getUserMute() {
		if (userMute == null) {
			userMute = new JCheckBox();
			userMute.setText("Mute");
			userMute.setBounds(new Rectangle(new Point(145, 225), userMute.getPreferredSize()));
		}
		return userMute;
	}
	
	
	public JCheckBox getMonitorCheckBox() {
		if (monitor == null) {
			monitor = new JCheckBox();
			monitor.setText("Monitor");
			monitor.setBounds(new Rectangle(new Point(145, 255), monitor.getPreferredSize()));
			monitor.setSelected(true);
		}
		return monitor;
	}
	
	
	private JSeparator getHorizontalSeparator() {
		if (separator1 == null) {
			separator1 = new JSeparator();
			separator1.setBounds(5, 165, 350, 2);
		}
		return separator1;
	}
	
	
	private JProgressBar getUserCalling() {
		if (userCalling == null) {
			userCalling = new JProgressBar();
			userCalling.setBounds(15, 325, 70, 15);
			userCalling.setPreferredSize(new Dimension(70,15));
			userCalling.setFont(new Font("Arial", Font.PLAIN, 10));
			userCalling.setStringPainted(true);
			userCalling.setString("calling");
			setUserIndeterminate();
			userCalling.setVisible(false);
		}
		return userCalling;
	}
	
	
	
	private JButton getAudioCallButton() {
		if (audioButton == null) {
			audioButton = new JButton("");
			audioButton.setBounds(new Rectangle(new Point(10, 285), new Dimension(32,32)));
			audioButton.setToolTipText((String)owner.getChatOwner().getActionManager().getAudioCallAction().getValue(Action.SHORT_DESCRIPTION));
			audioButton.setActionCommand(owner.getUser().getUsername());
			audioButton.setIcon((Icon)owner.getChatOwner().getActionManager().getAudioCallAction().getValue(Action.SMALL_ICON));
			audioButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if ( owner.getConnection() == null ) {
						owner.getChatOwner().getActionManager().getSendMessageAction().setUserExternal(owner.getUser());
						
						owner.getChatOwner().getActionManager().getSendMessageAction().actionPerformed(e);
					}

					userCalling.setVisible(true);
					setUserIndeterminate();
					
					owner.getChatOwner().getActionManager().getAudioCallAction().actionPerformed(e);
				}
			});
		}
		return audioButton;
	}
	
	
	private JButton getVideoCallButton() {
		if (videoButton == null) {
			videoButton = new JButton("");
			videoButton.setBounds(new Rectangle(new Point(57, 285), new Dimension(32,32)));
			videoButton.setToolTipText((String)owner.getChatOwner().getActionManager().getVideoCallAction().getValue(Action.SHORT_DESCRIPTION));
			videoButton.setActionCommand(owner.getUser().getUsername());
			videoButton.setIcon((Icon)owner.getChatOwner().getActionManager().getVideoCallAction().getValue(Action.SMALL_ICON));
			videoButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					if ( owner.getConnection() == null ) {
						owner.getChatOwner().getActionManager().getSendMessageAction().setUserExternal(owner.getUser());
						
						owner.getChatOwner().getActionManager().getSendMessageAction().actionPerformed(e);
					}

					userCalling.setVisible(true);
					setUserIndeterminate();
					
					owner.getChatOwner().getActionManager().getVideoCallAction().actionPerformed(e);
				}
			});
		}
		return videoButton;
	}
	
	
	private ActionEvent stopCallEvent = null;
	
	public JButton getStopCallButton() {
		if (stopCallButton == null) {
			stopCallButton = new JButton("");
			stopCallButton.setBounds(new Rectangle(new Point(105, 285), new Dimension(32,32)));
			stopCallButton.setToolTipText((String)owner.getChatOwner().getActionManager().getStopCallAction().getValue(Action.SHORT_DESCRIPTION));
			
			stopCallButton.setIcon((Icon)owner.getChatOwner().getActionManager().getStopCallAction().getValue(Action.SMALL_ICON));
			stopCallButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {

					ClientBindObject cbo = ClientApplication.clientBinding.get(owner.getUser().getUsername());
					
					Call call = cbo.getCall();

					String cmd = "C";

					if ( call != null && ( call.isVideoEstablished() || call.isAudioEstablished() ) ) {
						cmd = "C";
					}
					else {
						cmd = "W";
					}
						
					ActionEvent event = new ActionEvent(stopCallButton, 0, owner.getUser().getUsername() + " " + cmd);
					stopCallEvent = event;
					
//					owner.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
					
					new Thread(new Runnable() {
						@Override
						public void run() {
							owner.getChatOwner().getActionManager().getStopCallAction().actionPerformed(stopCallEvent);
//							owner.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
						}
					}).start();
					
					userCalling.setVisible(false);
				}
			});
		}
		return stopCallButton;
	}
	
	
	private void initComponents() {
		
		this.setLayout(null);
		
		peerVideoCardLayout = new CardLayout();
		userVideoCardLayout = new CardLayout();
		
		noVideoPicture = new JLabel(ImageCreator.createImageIcon(StreamingPanel.class, "peer_no_video.png"));
		noMonitorPicture = new JLabel(ImageCreator.createImageIcon(StreamingPanel.class, "user_no_video.png"));
		
		add(getUserAvatarButton());
		add(getPeerAvatarButton());

		add(getPeerVideoPanel());
		add(getUserVideoPanel());
		add(getPeerVolumeSlider());
		add(getPeerMute());
//		add(getUserVolumeSlider());
//		add(getUserMute());
		add(getMonitorCheckBox());
		add(getHorizontalSeparator());
		add(getUserCalling());
		add(getAudioCallButton());
		add(getVideoCallButton());
		add(getStopCallButton());

/*
		// compute preferred size
		{
			Dimension preferredSize = new Dimension();
			for(int i = 0; i < getComponentCount(); i++) {
				Rectangle bounds = getComponent(i).getBounds();
				preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width);
				preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height);
			}
			Insets insets = getInsets();
			preferredSize.width += insets.right;
			preferredSize.height += insets.bottom;
			setMinimumSize(preferredSize);
			setPreferredSize(preferredSize);
		}
*/
	}


	public JButton getPeerAvatarButton() {
		if (peerAvatar == null) {
			peerAvatar = new JButton();
			peerAvatar.setBounds(195, 10, 50, 50);
			peerAvatar.setIcon(ImageCreator.createImageIcon(StreamingPanel.class, "/avatars/" + owner.getUser().getAvatar() + ".png"));
		}
		
		return peerAvatar;
	}
	
	public JButton getUserAvatarButton() {
		if (userAvatar == null) {
			userAvatar = new JButton();
			userAvatar.setIcon(ImageCreator.createImageIcon(ChatDialog.class, "/avatars/" + owner.getClientUser().getAvatar() + ".png"));
			userAvatar.setBounds(195, 175, 50, 50);
			userAvatar.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					AvatarDialog avatarDialog = new AvatarDialog(owner);
					avatarDialog.setVisible(true);
				}
			});
		}
		
		return userAvatar;
	}
	
	

	private void setPeerIndeterminate() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				peerCalling.setIndeterminate(true);
			}
		});
	}
	

	private void setUserIndeterminate() {
		SwingUtilities.invokeLater(new Runnable() {
			@Override
			public void run() {
				userCalling.setIndeterminate(true);
			}
		});
	}
	

	// calling accept panel
	



	
	private JProgressBar getPeerCalling() {
		if (peerCalling == null) {
			peerCalling = new JProgressBar();
			peerCalling.setBounds(200, 140, 70, 15);
			peerCalling.setPreferredSize(new Dimension(70,15));
			peerCalling.setFont(new Font("Arial", Font.PLAIN, 10));
			peerCalling.setStringPainted(true);
			peerCalling.setString("calling");
			setPeerIndeterminate();
			peerCalling.setVisible(false);
		}
		return peerCalling;
	}
	

	
	private JTextArea getCallingLabel() {
		if (callingMessage == null) {
			callingMessage = new JTextArea();
			callingMessage.setPreferredSize(new Dimension(175, 70));
			callingMessage.setFont(new Font("Arial", Font.BOLD, 12));
			callingMessage.setBackground(new Color(230,230,230));
			callingMessage.setMargin(new Insets(2, 7, 2, 5));
			callingMessage.setBorder(BorderFactory.createLoweredBevelBorder());
			callingMessage.setEditable(false);
			callingMessage.setLineWrap(true);
			callingMessage.setWrapStyleWord(true);
		}
		return callingMessage;
	}
	
	
	public void setCallingMessage(String message) {
		if (callingMessage != null) {
			callingMessage.setText(message);
		}
	}
	
	/**
	 * Sakriva calling progress bar.
	 */
	public void hideUserCallingProgress() {
		if ( userCalling != null ) {
			userCalling.setVisible(false);
		}
	}
	
	public void hidePeerCallingProgress() {
		if ( peerCalling != null ) {
			peerCalling.setVisible(false);
		}
	}
	
	public void showUserCallingProgress() {
		if ( userCalling != null ) {
			userCalling.setVisible(true);
		}
	}
	
	public void showPeerCallingProgress() {
		if ( peerCalling != null ) {
			peerCalling.setVisible(true);
		}
	}
	
	
	private JPanel peerCallAcceptPanel;
	private JPanel peerNoVideoPanel;
	private JPanel peerVideoPanel;
	
	private JPanel getPeerCallAccept() {
		if (peerCallAcceptPanel == null) {
			peerCallAcceptPanel = new JPanel(new BorderLayout());
			peerCallAcceptPanel.add(getCallingLabel(), BorderLayout.NORTH);
			peerCallAcceptPanel.add(getPeerCalling(), BorderLayout.SOUTH);
			JPanel pan = new JPanel();
			pan.setLayout(new FlowLayout(FlowLayout.CENTER));
			pan.add(getYesButton());
			pan.add(getNoButton());
			peerCallAcceptPanel.add(pan, BorderLayout.CENTER);
		}
		return peerCallAcceptPanel;
	}
	
	private JPanel getPeerNoVideo() {
		if (peerNoVideoPanel == null) {
			peerNoVideoPanel = new JPanel();
//			peerNoVideoPanel.add(new JLabel("NO VIDEO"));
			peerNoVideoPanel.setLayout(null);
			noVideoPicture.setBounds(new Rectangle(0,0,176,144));
			peerNoVideoPanel.add(noVideoPicture);
			
		}
		return peerNoVideoPanel;
	}
	
	private JPanel getPeerVideo() {
		if (peerVideoPanel == null) {
			peerVideoPanel = new JPanel();
			peerVideoPanel.setLayout(null);
		}
		return peerVideoPanel;
	}

	private JPanel userNoVideoPanel;
	private JPanel userVideoPanel;
	
	
	private JPanel getUserNoVideo() {
		if (userNoVideoPanel == null) {
			userNoVideoPanel = new JPanel();
			userNoVideoPanel.setLayout(null);
//			userNoVideoPanel.add(new JLabel("NO MONITOR"));
			noMonitorPicture.setBounds(new Rectangle(0,0,128,96));
			userNoVideoPanel.add(noMonitorPicture);
		}
		return userNoVideoPanel;
	}
	
	private JPanel getUserVideo() {
		if (userVideoPanel == null) {
			userVideoPanel = new JPanel();
			userVideoPanel.setLayout(null);
		}
		return userVideoPanel;
	}
	
	
	
	public void setVideoComponent(JComponent videoComponent) {
		videoComponent.setBounds(new Rectangle(0,0,176,144));
		peerVideoPanel.add(videoComponent);
	}
	
	public void setMonitorVideoComponent(JComponent monitorVideoComponent) {
		monitorVideoComponent.setBounds(new Rectangle(0,0,128,96));
		userVideoPanel.add(monitorVideoComponent);
	}
	
	private int value = -1;

	private JButton getYesButton() {
		if (yesButton == null) {
			yesButton = new JButton();
			yesButton.setText("Yes");
			yesButton.setBounds(245, 95, 50, yesButton.getPreferredSize().height);
			yesButton.addActionListener(new ActionListener() {
				@Override
				public synchronized void actionPerformed(ActionEvent e) {
					synchronized ( syncObject ) {
						value = 1;
						syncObject.notify();
					}
				}
			});
		}
		return yesButton;
	}
	
	
	public JButton getNoButton() {
		if (noButton == null) {
			noButton = new JButton();
			noButton.setText("No");
			noButton.setBounds(300, 95, 50, noButton.getPreferredSize().height);
			noButton.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					synchronized ( syncObject ) {
						value = 0;
						syncObject.notify();
					}
				}
			});
		}
		return noButton;
	}
	
	private Object syncObject = new Object();
	
	public int showAcceptPanel(String messsage) {

		callingMessage.setText(messsage);
		showPeerCallingProgress();
		
		peerVideoCardLayout.show(peerVideo, "c2");
		
		synchronized ( syncObject ) {
			try {
				syncObject.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}

		return value;
	}

	
	public void showNoVideoPanel() {
		peerVideoCardLayout.show(peerVideo, "c1");
	}
	
	public void showVideoPanel() {
		peerVideoCardLayout.show(peerVideo, "c3");
	}
	
	public void showMonitorNoVideoPanel() {
		userVideoCardLayout.show(userVideo, "c1");
	}
	
	public void showMonitorVideoPanel() {
		userVideoCardLayout.show(userVideo, "c2");
	}
	
    
    public void refreshVideo() {
    	SwingUtilities.updateComponentTreeUI(peerVideo);
    	SwingUtilities.updateComponentTreeUI(userVideo);
    }
	
    
    public void removeListeners() {
    	try {
	    	monitor.removeActionListener(monitor.getActionListeners()[0]);
	    	peerMute.removeActionListener(peerMute.getActionListeners()[0]);
	    	peerVolume.removeChangeListener(peerVolume.getChangeListeners()[0]);
    	}
    	catch (Exception e) {
    		
    	}
    }
    
}
